package com.inspur.xiaoju.service.impl;

import com.inspur.xiaoju.model.Captcha;
import com.inspur.xiaoju.repository.CaptchaRepository;
import com.inspur.xiaoju.service.CaptchaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;

@Service
public class CaptchaServiceImpl implements CaptchaService {

    @Autowired
    private CaptchaRepository captchaRepository;
    
    private static final int CAPTCHA_LENGTH = 4;
    private static final String CAPTCHA_CHARS = "0123456789";
    private static final long CAPTCHA_EXPIRE_TIME = 5 * 60 * 1000; // 5分钟过期
    
    /**
     * 生成并保存验证码到MongoDB，同时生成验证码图片
     * @param captchaId 已存在的验证码ID（如果有）
     * @return 包含验证码ID和图片的对象
     */
    @Override
    public Map<String, String> generateAndSaveCaptcha(String captchaId) {
        // 删除已存在的验证码
        if (StringUtils.hasText(captchaId)) {
            captchaRepository.deleteById(captchaId);
        }

        // 生成随机验证码
        String captchaText = generateRandomCaptcha(CAPTCHA_LENGTH);
        
        // 生成唯一ID
        String newId = UUID.randomUUID().toString();
        
        // 创建并保存Captcha实体
        Captcha captcha = new Captcha();
        captcha.setId(newId);
        captcha.setCaptcha(captchaText);
        captcha.setCreateTime(new Date());
        captchaRepository.save(captcha);
        
        // 生成验证码图片
        String captchaImage = generateCaptchaImage(captchaText);
        
        // 返回包含ID和图片的对象
        Map<String, String> data = new HashMap<>();
        data.put("id", newId);
        data.put("img", captchaImage);
        return data;
    }
    
    /**
     * 校验验证码是否正确
     * @param id 验证码ID
     * @param captcha 用户输入的验证码
     * @return 验证结果
     */
    @Override
    public boolean validateCaptcha(String id, String captcha) {
        if (id == null || captcha == null) {
            return false;
        }
        
        // 查询MongoDB中的验证码
        Optional<Captcha> captchaOptional = captchaRepository.findById(id);
        
        if (!captchaOptional.isPresent()) {
            return false;
        }
        
        Captcha captchaEntity = captchaOptional.get();
        
        // 获取验证码和创建时间
        String storedCaptcha = captchaEntity.getCaptcha();
        Date createTime = captchaEntity.getCreateTime();
        
        // 验证码过期检查
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - createTime.getTime();
        if (elapsedTime > CAPTCHA_EXPIRE_TIME) {
            // 验证码已过期，删除已过期的验证码
            captchaRepository.deleteById(id);
            return false;
        }
        
        // 验证码匹配检查（忽略大小写）
        boolean isValid = captcha.equalsIgnoreCase(storedCaptcha);
        
        // 无论验证成功与否，都删除已使用的验证码
        captchaRepository.deleteById(id);
        
        return isValid;
    }
    
    /**
     * 生成随机验证码字符串
     */
    private String generateRandomCaptcha(int length) {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(CAPTCHA_CHARS.length());
            sb.append(CAPTCHA_CHARS.charAt(index));
        }
        
        return sb.toString();
    }
    
    /**
     * 生成验证码图片并转为Base64编码
     */
    private String generateCaptchaImage(String captchaText) {
        try {
            int width = 100;
            int height = 40;
            
            // 创建图像缓冲区
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = image.getGraphics();
            
            // 设置背景色
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, width, height);
            
            // 绘制干扰线
            Random random = new Random();
            g.setColor(Color.LIGHT_GRAY);
            for (int i = 0; i < 20; i++) {
                int x1 = random.nextInt(width);
                int y1 = random.nextInt(height);
                int x2 = random.nextInt(width);
                int y2 = random.nextInt(height);
                g.drawLine(x1, y1, x2, y2);
            }
            
            // 绘制验证码
            g.setFont(new Font("Arial", Font.BOLD, 24));
            for (int i = 0; i < captchaText.length(); i++) {
                g.setColor(new Color(random.nextInt(100), random.nextInt(100), random.nextInt(100)));
                g.drawString(String.valueOf(captchaText.charAt(i)), 20 * i + 10, 25);
            }
            
            g.dispose();
            
            // 转换为Base64
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            byte[] imageBytes = baos.toByteArray();
            
            return "<img src='data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes) + "'/>";
        } catch (Exception e) {
            throw new RuntimeException("生成验证码图片失败", e);
        }
    }
}